package org.meandslava.calc.arithmetic;

import java.util.Iterator;
import java.util.LinkedList;

import android.text.Editable;

public class Expression extends Number {
	private LinkedList<Term> expression = new LinkedList<Term>();
	private boolean lockExpression = false;
	private boolean isRootExpression = false;
	
	public void setExpressionAsRoot(boolean isRoot){
		isRootExpression = isRoot;
	}
	
	public void addTerm(Term t){
		expression.add(t);
	}
	
	@Override
	public double getValue() {
		LinkedList<Term> tmp = new LinkedList<Term>(expression);
		Term term;
		double val = 0;
		while(tmp.size()!=0){
			term = tmp.poll();
			val = term.calc(val, tmp);
		}
		return val;
	}
	@Override
	public boolean process(String categoryTag, String action) {
		if (lockExpression) {
			return false;
		}

		if (expression.size() > 0){
			if (!expression.getLast().process(categoryTag, action)) {
				if (categoryTag.equals(CATEGORY_EXPRESSION)) {
					if(action.equals(")")){
						lockExpression = true;
					}else if(action.equals("(") && expression.getLast() instanceof Binary){
						expression.add(TermFactory.create(categoryTag, action));
					}
				} else {
					expression.add(TermFactory.create(categoryTag, action));
				}
			}
		}else{
			if (!action.equals(")")) {
				expression.add(TermFactory.create(categoryTag, action));
			}
		}
		return true;
	}
	
	@Override
	public boolean back() {
		if (expression.size() == 0) {
			return true;
		}
		if (lockExpression) {
			lockExpression = false;
			return false;
		}
		if (expression.getLast().back()) {
			expression.removeLast();
			//expression.pop();
		}
		return false;
	}
	
	@Override
	public void write(Editable editable) {
		if(!isRootExpression){
			editable.append('(');
		}
		Iterator<Term> i = expression.iterator();
		while(i.hasNext()){
			i.next().write(editable);
		}
		if(!isRootExpression && lockExpression){
			editable.append(')');
		}
	}
	
	@Override
	public String toString() {
		double res = getValue();
		return format.format(res);
	}
}
